#ifndef SDF_H
#define SDF_H

#include <osg/Matrix>
#include <string>
#include <vector>
#include <osg/Vec3>
#include <BulletLibDefine.h>
#include <osg/Node>
#include <SDFDof.h>
class BULLET_EDITOR_DLL SDF : public osg::Node
{
public:
    SDF();
    virtual ~SDF();

    int getRigidPtrInt();
    void setRigidPtrInt(int intPtr);

    int getRigidPtrIntActual();
    void setRigidPtrIntActual(int intPtr);

    std::string getOsgNodeName();
    void setOsgNodeName(const std::string& nodeName);
    //grid releated
    osg::Vec3 getMinCoordinate();
    void setMinCoordinate(double x, double y, double z);

    osg::Vec3 getNodeCountVector();
    void setNodeCountVector(int x, int y, int z);

    int getNodeCount();
    void setNodeCount(int intValue);

    osg::Vec3 getdxdydz();
    void setdxdydz(double dx, double dy, double dz);

    osg::Vec3 getMaxCoordinate();
    void setMaxCoordinate(double x, double y, double z);

    //samplePoint
    int getPointCount();
    void setPointCount(int intValue);
    osg::Vec3 getPointCoordinate(int index);
    osg::Vec3 getPointCoordinateInWorldFrame(int index);


    //matrix
    void setMatrix(const osg::Matrix& m);
    osg::Matrix getMatrix();

    //
    std::vector<float>& getGridValue();
    std::vector<osg::Vec3>& getSampleValue();

    //charge function
    bool isPointInGridInWorldFrame(float x, float y, float z);
    bool isPointClosedInWorldFrame(float x, float y, float z);
    bool isPointClosedByIJK(int x, int y, int z);
    bool isPointClosedByIJK2(int x, int y, int z);
    bool isPointClosedByIJK3(int x, int y, int z);
    bool isPointClosedByIJK4(int x, int y, int z);
    bool isPointEncloseClosedInWorldFrame(float x, float y, float z);

    bool isPointNearSharpEdgeInWorldFrame(float x, float y, float z);
    bool isPointNearSharpEdge(float x, float y, float z);

    //value function
    float getGridValueByIJK(int i, int j, int k);
    float getGridValueByPosition(float x, float y, float z);
    float getGridValueByWorldFrame(float x, float y, float z);
    osg::Vec3 getPositionInSDFFrameByIJK(int i, int j, int k);
    osg::Vec3 getGradientByIJK(int i, int j, int k);
    osg::Vec3 getGradientByPosition(float x, float y, float z);
    osg::Vec3 getGradientByPositionInWorldFrame(float x, float y, float z);
    void enclosing_indices(osg::Vec3& point
                           , int& i0
                           , int& j0
                           , int& k0
                           , int& i1
                           , int& j1
                           , int& k1);
    double getBoxSize();

    //dof
    osg::ref_ptr<SDFDof> getSDFDof();

    //if can collision
    void setCollisionEnable(bool boolValue);
    bool getCollisionEnable();
protected:
    osg::Vec3 getPositionInLocalFrame(float x, float y, float z);
    bool isEdgeThroughBy4Value(float v0, float v1, float v2, float v3);
    bool isNormalParallelBy2Index(int i0,int j0,int k0,
                                  int i1,int j1,int k1);
private:
    osg::Matrix m_matrix;
    int m_rigidPtrInt;//same with sdf xml files
    int m_rigidPtrIntActual;//same with bullet current
    std::string m_osgNodeName;
    //grid
    osg::Vec3 m_minCoordinate;
    osg::Vec3 m_nodeCountVector;
    int m_nodeCount;
    osg::Vec3 m_dxdydz;
    osg::Vec3 m_maxCoordinate;
    std::vector<float> m_gridValue;
    //sample
    std::vector<osg::Vec3> m_samplePoint;
    int m_pointCount;

    //dof
    osg::ref_ptr<SDFDof> m_dof;

    bool m_collisionEnable;
};

#endif // SDF_H
